﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using CNShapes;
using BobcatMultiTouch;
using BobcatUtility;
using CNUtility;
using CNNetworking;

namespace CNTestApp
{
    public partial class Form1 : Form
    {

        /// <summary>
        /// Constructor.
        /// </summary>
        public Form1()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Called when the form is first loaded. We set up the app here.
        /// </summary>
        private void Form1_Load(object sender, EventArgs e)
        {
            // We load the user-preferences...
            UserPreferences.getInstance().initialize();
            setupDefaultPreferences();

            // We intialize the MTIM...
            try
            {
                MultiTouchInputManager.getInstance().initializeFromFile(CONFIG_FILENAME);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

            // We set-up the session...
            Session.getInstance().addPage();
            ctrlSession.Session = Session.getInstance();
            ctrlSession.ActivePageBackgroundImage = Utility.getImageFromResources("lined_paper.jpg");
            ctrlSession.ThumbnailBackgroundImage = Utility.getImageFromResources("lined_paper_small.jpg");

            // We set up the network settings...
            setupNetworking();
        }

        /// <summary>
        /// Called shortly before the form closes. We clean up the app here.
        /// </summary>
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            NetworkingServer.getInstance().stopServer();
            NetworkingClient.getInstance().disconnect();
            MultiTouchInputManager.getInstance().saveToFile(CONFIG_FILENAME);
        }

        // Sets us default properties for the app. This will only set the properties if they
        // are not already in the preferences config file.
        private void setupDefaultPreferences()
        {
            PropertyBag properties = UserPreferences.getPropertyBag();

            // User info...
            properties.setDefaultValueString("UserInfo.FirstName", "");
            properties.setDefaultValueString("UserInfo.LastName", "");

            // Properties for the GestureHandler_DragPicture...
            properties.setDefaultValueInt("GestureHandler_DragPicture.PressAndHoldInterval", 250);

            // Networking settings...
            properties.setDefaultValueInt("Networking.Port", 9559);
            properties.setDefaultValueBool("Networking.StartServerAtStartup", false);
            properties.setDefaultValueBool("Networking.ShareServerList", true); // We share the details of other machines / users we know about with any other people we connect to in a drawing session.
            IList<ConnectionSettings> connectionSettings = new List<ConnectionSettings>();
            connectionSettings.Add(new ConnectionSettings{FirstName="Richard", LastName="Shepherd", HostName="localhost"});
            properties.setDefaultValueList("Networking.ServerConnectionList", connectionSettings);
        }

        // Sets us networking parts of the UI...
        private void setupNetworking()
        {
            // We fill in the listbox showing other users that we can connect to...
            IList<ConnectionSettings> userSettings = UserPreferences.getPropertyBag().getList<ConnectionSettings>("Networking.ServerConnectionList");
            foreach (ConnectionSettings cs in userSettings)
            {
                listServers.Items.Add(cs);
            }
            if (listServers.Items.Count >= 1)
            {
                listServers.SelectedIndex = 0;
            }

            // We observe the client list so that we can show who else is connected to this session...
            NetworkingClient.getInstance().ClientListUpdatedEvent += onClientListUpdated;
        }

        // Called when the list of users connected to this session changes...
        void onClientListUpdated(object sender, NetworkingClient.ClientListUpdatedArgs e)
        {
            listUsersInSession.Items.Clear();
            foreach (string strName in e.ClientNames)
            {
                listUsersInSession.Items.Add(strName);
            }
        }

        // Called when the name boxes change. We update the name in the user-preferences.
        private void txtFirstName_TextChanged(object sender, EventArgs e)
        {
            UserPreferences.getPropertyBag().setString("UserInfo.FirstName", txtFirstName.Text);
        }
        private void txtLastName_TextChanged(object sender, EventArgs e)
        {
            UserPreferences.getPropertyBag().setString("UserInfo.LastName", txtLastName.Text);
        }

        // Called when the act-as-server checkbox is changed.
        private void chkActAsServer_CheckedChanged(object sender, EventArgs e)
        {
            if (chkActAsServer.Checked == true)
            {
                NetworkingServer.getInstance().startServer();

                // We connect to ourself to get user-list updates etc, just like 
                // other clients...
                ConnectionSettings serverSettings = NetworkingClient.getInstance().getClientConnectionSettings();
                NetworkingClient.getInstance().connect(serverSettings);
            }
            else
            {
                NetworkingServer.getInstance().stopServer();
            }
        }

        // Called when the Connect button is pressed.
        private void cmdConnect_Click(object sender, EventArgs e)
        {
            // We connect to the selected server...
            ConnectionSettings serverSettings = (ConnectionSettings)listServers.SelectedItem;
            NetworkingClient.getInstance().connect(serverSettings);
        }

        // File that stores XML config about which sources are used, wiimote calibration etc...
        private const string CONFIG_FILENAME = "MultiTouchConfig.xml";

        /// <summary>
        /// Called when the network connect button is pressed on the toolbar.
        /// </summary>
        private void tbConnect_Click(object sender, EventArgs e)
        {
            // We hide the connect button and show the disconnect button...
            tbConnect.Visible = false;
            tbDisconnect.Visible = true;

            // We connect to the selected server...
            ConnectionSettings serverSettings = (ConnectionSettings)listServers.SelectedItem;
            NetworkingClient.getInstance().connect(serverSettings);
        }

        /// <summary>
        /// Called when the disconnect button is pressed on the toolbar.
        /// </summary>
        private void tbDisconnect_Click(object sender, EventArgs e)
        {
            // We hide the disconnect button and show the connect button...
            tbDisconnect.Visible = false;
            tbConnect.Visible = true;

            // We disconnect from the server...
            NetworkingClient.getInstance().disconnect();
        }

        private void tbUndo_Click(object sender, EventArgs e)
        {
            ctrlSession.undo();
        }

        private void tbRedo_Click(object sender, EventArgs e)
        {
            ctrlSession.redo();
        }

        private void tbNewSession_Click(object sender, EventArgs e)
        {
            Session.getInstance().newSession();
            Session.getInstance().addPage();
        }

        private void tbNewPage_Click(object sender, EventArgs e)
        {
            Session.getInstance().addPage();
        }

        private void tbConfig_Click(object sender, EventArgs e)
        {
            MultiTouchInputManager.getInstance().showConfigScreen();
        }



    }
}
